#include <iostream>
#include <sstream>
#include <string>
#include <map>

#include "Server.h"

#include "Dealer.h"
#include "DealerPreFlop.h"
#include "DealerFlop.h"
#include "DealerTurn.h"
#include "DealerRiver.h"

#include "QtApp.h"
#include "../Common/Card.h"
#include "../Common/Player.h"
#include "../Common/PokerTool.h"
#include "../Common/DataNetworkRepresentation.h"

using namespace std;

/*
 * Vrai si il doit délivrer les cartes
 * Faux si il ne doit pas délivrer les cartes
 */
bool Server::isDistributionAll(int stateGame)
{
	if(Game::getGame()->gameinfo.getGameState() == stateGame)
	{
		if(Game::getGame()->dealer->isDelivering())
		{
			Game::getGame()->dealer->isDistribute = false;
			return true;

		}
	}
	return false;
}
bool Server::isDistributionPreFlop()
{
	return isDistributionAll(0);
}
bool Server::isDistributionFlop()
{
	return isDistributionAll(1);
}
bool Server::isDistributionTurn()
{
	return isDistributionAll(2);
}
bool Server::isDistributionRiver()
{
	return isDistributionAll(3);
}
/*
 * Fonction appelé a la fin d'une partie,
 * elle attribut le pot
 * elle met à joujoueursMemoiret l'interface graphique de la partie actuelle
 * elle prépare l'interface pour le partie suivante (telle que le nouvelle onglet)
 * elle réinitialise des variables globales
 */
void Server::endGame(QtApp *app)
{
	// envoi un message en fin de partie aux clients(joueurs)
	Game::getGame()->messageEndGame();

	Game::getGame()->attributPot();

	// Création nouvel d'un onglet de fin de partie
	app->createPage();

	// remise à 0 des valeurs /
	Game::getGame()->gameinfo.setGameState(0);
	Game::getGame()->endGame = 0;
	//TODO
	//Game::getGame()->gameinfo.setCurrentPlayer(1);
	Game::getGame()->twoPlayerOnPlay = 0;
	Game::getGame()->dealer->isDistribute = true;
	Game::getGame()->countAction=0;
	Game::getGame()->gameinfo.getPlayer(2).setMise( 0 );
	Game::getGame()->gameinfo.getPlayer(1).setMise( 0 );
	Game::getGame()->gameinfo.setPot(0);

	//Décrementation du nombre de même partie à jouer
	Game::getGame()->dealer->compteurDePartie--;

//	int pos1 = Game::getGame()->gameinfo.getPlayer(1).getPosition();
//	int pos2 = Game::getGame()->gameinfo.getPlayer(1).getPosition();
//	Game::getGame()->gameinfo.getPlayer(1).setPosition(pos2);
//	Game::getGame()->gameinfo.getPlayer(2).setPosition(pos1);

	cout << "--------------------Fin d'une partie---------------------" << endl;
}
/*
 * Fonction appelé tous les secondes,
 * elle alterne le joueur courant
 * elle appel le dealer qui va distrubuer les cartes
 */
void Server::goPlayer(char **argvGolbal,QtApp *app) throw (Exception)
{
	//Si fin de partie on stop
	if(Game::getGame()->endGame == 1) endGame(app);

	Game::getGame()->countAction++;

	cout << "----------- Coup joueur (" << Game::getGame()->gameinfo.getCurrentPlayer() << ") --------------" << endl;

	char request[300];

	string ipjoueur1 = PokerTool::stringToChar(argvGolbal[1]);
	string ipjoueur2 = PokerTool::stringToChar(argvGolbal[2]);

	string ipport1 = PokerTool::stringToChar(argvGolbal[3]);
	string ipport2 = PokerTool::stringToChar(argvGolbal[4]);

	string strategy1 = PokerTool::stringToChar(argvGolbal[5]);
	string strategy2 = PokerTool::stringToChar(argvGolbal[6]);

	// Les 4 distributions suivant : gestion de l'affichage et distributio, des cartes : if(distribution ==0)
	//pre-flop, distribution des cartes au joueur
	if(isDistributionPreFlop())
	{
		cout << "-------------Start isDistributionPreFlop------------------" << endl;
		//initialisation des 2 variables de début de partie
		Game::getGame()->twoPlayerOnPlay = 0;
		//Game::getGame()->gameinfo.setCurrentPlayer(1);

		//initialise les cards du paquet et récupère les nouveaux joueurs
		Game::getGame(ipjoueur1, ipjoueur2,ipport1,ipport2,strategy1,strategy2);

		cout << "-------------Center isDistributionPreFlop------------------" << endl;
		Game::getGame()->dealer->distribution(Game::getGame()->gameinfo.getPlayers()[1],Game::getGame()->gameinfo.getPlayers()[2]);

		cout << "------------------ information joueur 1 -------------------" << endl;
		Game::getGame()->gameinfo.getPlayers()[1].printHandle();

		cout << "------------------ information joueur 2 -------------------" << endl;
		Game::getGame()->gameinfo.getPlayers()[2].printHandle();

		cout << "------------------ Carte du jeu restante -------------------" << endl;
		Game::getGame()->dealer->printCards(Game::getGame()->cards);

		app->updateDeliveryPreFlop();
		cout << "-------------Finish isDistributionPreFlop------------------" << endl;
		cout << "-----------------------------------------------------------" << endl << endl;
	}
	//flop, 3 cartes sur le flop
	else if(isDistributionFlop())
	{
		cout << "-------------Start isDistributionFlop------------------" << endl;
		Game::getGame()->twoPlayerOnPlay = 0;
		Game::getGame()->gameinfo.setCurrentPlayer(1);

		Game::getGame()->dealer->distribution(Game::getGame()->gameinfo.getPlayers()[1],Game::getGame()->gameinfo.getPlayers()[2]);
		app->updateDeliveryFlop();
		cout << "-------------Finish isDistributionFlop------------------" << endl;
	}
	//turn, 4 cartes sur le flop
	else if(isDistributionTurn())
	{
		cout << "-------------Start isDistributionTurn------------------" << endl;
		Game::getGame()->twoPlayerOnPlay = 0;
		Game::getGame()->gameinfo.setCurrentPlayer(1);

		Game::getGame()->dealer->distribution(Game::getGame()->gameinfo.getPlayers()[1],Game::getGame()->gameinfo.getPlayers()[2]);
		app->updateDeliveryTurn();
		cout << "-------------Finish isDistributionTurn------------------" << endl;
	}
	//river : 5 cartes sur le flop
	else if(isDistributionRiver())
	{
		cout << "-------------Start isDistributionRiver------------------" << endl;
		Game::getGame()->twoPlayerOnPlay = 0;
		Game::getGame()->gameinfo.setCurrentPlayer(1);

		Game::getGame()->dealer->distribution(Game::getGame()->gameinfo.getPlayers()[1],Game::getGame()->gameinfo.getPlayers()[2]);
		app->updateDeliveryRiver();
		cout << "-------------Finish isDistributionRiver------------------" << endl;
	}
	//si l'un des 2 joueurs n'as plus d'argent
	if(Game::getGame()->gameinfo.getPlayer(1).getBankrollInt() <=0 || Game::getGame()->gameinfo.getPlayer(2).getBankrollInt() <= 0) Game::getGame()->endGame = 1;

	//Utilisation du protocole de tranfert en XML
	if(USE_COMMUNICATION_XML)
		strcpy(request, Game::getGame()->gameinfo.toXml().toStdString().c_str() );
	//Utilisation du protocole version langage formelle
	else
		strcpy(request, Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getCurrentPlayer()).toString(
				Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getOtherCurrentPlayer()).getBetInt()
				,Game::getGame()->gameinfo.getGameState(),0,0
		).c_str()  );

	cout << "Game::getGame()->gameinfo.getPlayer(Game::getGame()->currentPlayer).toString()" <<
			Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getCurrentPlayer()).toString(
					Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getOtherCurrentPlayer()).getBetInt()
					,Game::getGame()->gameinfo.getGameState(),0,0
			) << endl;

	string response;

	//Utilisation du protocole de tranfert en XML
	if(USE_COMMUNICATION_XML)
	{
		// envoi le message au serveur et recupère la réponse
		response = Game::getGame()->ie.sendMessageGame(request, Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getCurrentPlayer()));

		cout << "-----------DataNetworkRepresentation----------------------" << endl;
	    QString res = response.c_str();
	    DataNetworkRepresentation::decoding( res, Game::getGame()->gameinfo );
	}
	//Utilisation du protocole version langage formelle
	else
	{
		// envoi le message au serveur et recupère la réponse
		Game::getGame()->gameinfo.getPlayer(
				Game::getGame()->gameinfo.getCurrentPlayer()
		).setAction(
			Game::getGame()->ie.sendMessageGame(request,
								Game::getGame()->gameinfo.getPlayer(
										Game::getGame()->gameinfo.getCurrentPlayer()
								)
			).c_str()
		);
	}

	cout << "response du client : " << response << endl;

	//Gersstion des actions après avoi recu la réponse : fold, raise,
   	Game::getGame()->actionPlayer(Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getCurrentPlayer()),app);

	// Après la gestion du joueur on met à jour l'interface graphique
	cout << "Game::getGame()->gameinfo.countAction : " << Game::getGame()->countAction << endl;
   	cout << "Game::getGame()->gameinfo.getCurrentPlayer() : " << Game::getGame()->gameinfo.getCurrentPlayer() << endl;
	cout << "Game::getGame()->gameinfo.getCurrentPlayer() : " << Game::getGame()->gameinfo.getPlayer( Game::getGame()->gameinfo.getCurrentPlayer() ).getName().toStdString() << endl;

	app->upadteInterfaceGraphicOnPlayer(Game::getGame()->gameinfo.getPlayer(Game::getGame()->gameinfo.getCurrentPlayer()));

	//Si on est su le river
	if(Game::getGame()->gameinfo.getGameState() == 3)
	{
		if(Game::getGame()->gameinfo.getPlayer(1).getBetInt() == Game::getGame()->gameinfo.getPlayer(2).getBetInt() && Game::getGame()->twoPlayerOnPlay >= 2)
		{
			cout << "--------twoPlayerOnPlay : "<< Game::getGame()->twoPlayerOnPlay <<"--------------etat 3----------" << endl;
			Game::getGame()->gameinfo.getPlayer( Game::getGame()->plusFaiblemain() ).setAction(choice[0].c_str());
			cout << "-------------Fin de partie--------------------" << endl;
			endGame(app);

			// TODO: before endGame
			Game::getGame()->attributPot();
		}
	}
	//Si les conditions sont remplite alors incrémentation de la partie
	if(Game::getGame()->gameinfo.getPlayer(1).getBetInt() == Game::getGame()->gameinfo.getPlayer(2).getBetInt() && Game::getGame()->twoPlayerOnPlay >= 2 )
	{
		cout << "Game::getGame()->gameinfo.getPlayer(1).bet : " << Game::getGame()->gameinfo.getPlayer(1).getBetInt()  << endl;
		cout << "Game::getGame()->gameinfo.getPlayer(2).bet : " << Game::getGame()->gameinfo.getPlayer(2).getBetInt()  << endl;
		cout << "Game::getGame()->gameinfo.getGameState() :" << Game::getGame()->gameinfo.getGameState() << endl;
		Game::getGame()->dealer->isDistribute = true;
		Game::getGame()->twoPlayerOnPlay=0;
		Game::getGame()->gameinfo.incrementGameState();
	}
	//mise à jour des mises
	Game::getGame()->gameinfo.getPlayer(1).setMise( 0 );
	Game::getGame()->gameinfo.getPlayer(2).setMise( 0 );

	// changement joueur courant /
	if(Game::getGame()->gameinfo.getCurrentPlayer() == 1)
		Game::getGame()->gameinfo.setCurrentPlayer(2);
	else
		Game::getGame()->gameinfo.setCurrentPlayer(1);
}

Game * Server::initGame()
{
	Game::getGame()->gameinfo.setPot(0);
	Game *partie = new Game();
	return partie;
}

Server::Server()
{

}
